
package buffbuildergui;

import java.awt.Color;

import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;

import java.io.UnsupportedEncodingException;

import java.net.URI;

import java.net.URISyntaxException;

import java.util.ArrayList;

import java.util.Scanner;

import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

/**
 *
 * @author Michael Greene
 */
public class jfMainFrame extends javax.swing.JFrame{

    /** Creates new form jfMainFrame */
    public jfMainFrame() {
        initComponents();
        setBackground(Color.white);
        jpToolbox.setBorder(new LineBorder(Color.black,1,false));
        setFocusable(true);
        surface = new BevelArrow(this);
        jlpEditWindow.add(surface);
        surface.setSize(4000,4000);
        surface.setPreferredSize(new Dimension(4000,4000));
        surface.setVisible(true);
        //jlpEditWindow.moveToBack(surface);
        cm = new ComponentMover(surface);
        bypass = jlpEditWindow;//bypass the freaking auto-gen'd code being private >:(
    }
    
    
    
    String dialogString;
    static ArrayList<Buff> buffList = new ArrayList<Buff>();
    static ArrayList<Ability> abilityList = new ArrayList<Ability>();
    String buffChainName = "";
    static JLayeredPane bypass = null;
    ComponentMover cm;
    BevelArrow surface;

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    private void initComponents() {//GEN-BEGIN:initComponents

        jlpEditWindow = new javax.swing.JLayeredPane();
        jpToolbox = new javax.swing.JPanel();
        cmdNewBuff = new javax.swing.JButton();
        cmdNewAbility = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        newBuffChain = new javax.swing.JMenuItem();
        loadBuffChain = new javax.swing.JMenuItem();
        saveBuffChain = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        exportToBuffChain = new javax.swing.JMenuItem();
        importFromEntity = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jmiReadme = new javax.swing.JMenuItem();
        jmiHelp = new javax.swing.JMenuItem();
        jmiSource = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jpToolbox.setMaximumSize(new java.awt.Dimension(101, 32767));

        cmdNewBuff.setText("New Buff");
        cmdNewBuff.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmdNewBuffActionPerformed(evt);
            }
        });

        cmdNewAbility.setText("New Ability");
        cmdNewAbility.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmdNewAbilityActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jpToolboxLayout = new javax.swing.GroupLayout(jpToolbox);
        jpToolbox.setLayout(jpToolboxLayout);
        jpToolboxLayout.setHorizontalGroup(
            jpToolboxLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpToolboxLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jpToolboxLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(cmdNewBuff, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jpToolboxLayout.createSequentialGroup()
                        .addComponent(cmdNewAbility)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jpToolboxLayout.setVerticalGroup(
            jpToolboxLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jpToolboxLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(cmdNewAbility)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(cmdNewBuff)
                .addGap(0, 425, Short.MAX_VALUE))
        );

        jMenu1.setText("File");

        newBuffChain.setText("New Buff Chain");
        newBuffChain.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newBuffChainActionPerformed(evt);
            }
        });
        jMenu1.add(newBuffChain);

        loadBuffChain.setText("Load Buff Chain");
        loadBuffChain.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                loadBuffChainActionPerformed(evt);
            }
        });
        jMenu1.add(loadBuffChain);

        saveBuffChain.setText("Save Buff Chain");
        saveBuffChain.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveBuffChainActionPerformed(evt);
            }
        });
        jMenu1.add(saveBuffChain);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Translation");

        exportToBuffChain.setText("Export to Entities");
        exportToBuffChain.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportToBuffChainActionPerformed(evt);
            }
        });
        jMenu2.add(exportToBuffChain);

        importFromEntity.setText("Import from Entities");
        importFromEntity.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                importFromEntityActionPerformed(evt);
            }
        });
        jMenu2.add(importFromEntity);

        jMenuBar1.add(jMenu2);

        jMenu3.setText("Help");

        jmiReadme.setText("Getting Started");
        jmiReadme.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jmiReadmeActionPerformed(evt);
            }
        });
        jMenu3.add(jmiReadme);

        jmiHelp.setText("Get Help");
        jmiHelp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jmiHelpActionPerformed(evt);
            }
        });
        jMenu3.add(jmiHelp);

        jmiSource.setText("View Source");
        jmiSource.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jmiSourceActionPerformed(evt);
            }
        });
        jMenu3.add(jmiSource);

        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jpToolbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jlpEditWindow, javax.swing.GroupLayout.DEFAULT_SIZE, 873, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jlpEditWindow)
            .addComponent(jpToolbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }//GEN-END:initComponents

    private void exportToBuffChainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportToBuffChainActionPerformed
        if(buffChainName == "") {
            String input = "";
            input = JOptionPane.showInputDialog(jlpEditWindow,"Select a new Buff Chain Prefix.  Leave blank for no prefix.");
            
            if(input == null)
                return;
            buffChainName = input;
            this.setTitle("Buff Builder - " + buffChainName);
        }
        ArrayList<String> entityList = new ArrayList<String>();
        for(int i = 0; i < abilityList.size();i++) {
            Ability e = abilityList.get(i);
            AbilityPanel ep = (AbilityPanel)e.ownerPanel;
            try {
                String filename = "Ability" + buffChainName + e.name;
                entityList.add(filename + ".entity");
                PrintWriter pw = new PrintWriter("GameInfo/" + filename + ".entity","UTF-8");
                
                exportAbility(pw,e,ep);
                
                pw.flush();
                pw.close();
            } catch (FileNotFoundException f) {
            } catch (UnsupportedEncodingException f) {
            }
        }
        for(int i = 0; i < buffList.size(); i++) {
            Buff e = buffList.get(i);
            BuffPanel ep = (BuffPanel)e.ownerPanel;
            try {
                String filename = "Buff" + buffChainName + e.name;
                entityList.add(filename + ".entity");
                PrintWriter pw = new PrintWriter("GameInfo/" + filename + ".entity","UTF-8");
                
                exportBuff(pw,e,ep);
                
                pw.flush();
                pw.close();
            } catch (FileNotFoundException f) {
            } catch (UnsupportedEncodingException f) {
            }
        }
        try {
            File fs = new File("entity.manifest");
            Scanner s = new Scanner(fs);
            ArrayList<String> already = new ArrayList<String>();
            s.nextLine();// TXT
            s.nextLine();// entityNameCount
            while(s.hasNext()) {
                String input = s.nextLine();
                input = input.substring(input.indexOf("\"")+1);
                input = input.substring(0,input.length()-1);
                already.add(input);
            }
            for(int i = 0; i < entityList.size(); i++) {
                for(int j = 0; j < already.size(); j++) {
                    String n0 = entityList.get(i);
                    String n1 = already.get(j);
                    if(n0.equals(n1)) {
                        JOptionPane.showMessageDialog(this,"remove");
                        entityList.remove(i);
                        i--;
                        break;
                    }
                }
            }
            PrintWriter pw = new PrintWriter("entity.manifest", "UTF-8");
            pw.println("TXT");
            pw.println("entityNameCount " + (entityList.size() + already.size()));
            for(int i = 0; i < entityList.size(); i++) {
                pw.println("entityName \"" + entityList.get(i) + "\"");
            }
            for(int i = 0; i < already.size(); i++) {
                pw.println("entityName \"" + already.get(i) + "\"");
            }
            pw.println();
            pw.flush();
            pw.close();
        } 
        catch (UnsupportedEncodingException | FileNotFoundException e) {
            JOptionPane.showMessageDialog(this, "Failed to save entity.manifest\n" + e.toString());
        }

        JOptionPane.showMessageDialog(this,"Export complete");
        
    }//GEN-LAST:event_exportToBuffChainActionPerformed

    private void cmdNewBuffActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmdNewBuffActionPerformed
        String input = "";
        boolean loopAnyways = false;
        while(input.equals("") || loopAnyways)
        {
            loopAnyways = false;
            input = JOptionPane.showInputDialog(jlpEditWindow,"Select New Buff Name");
            if(input == null)
                return;

            for(int i = 0; i < buffList.size(); i++) {
                if(buffList.get(i).name.equals(input))
                {
                    JOptionPane.showMessageDialog(jlpEditWindow, "A buff already exists by that name");
                    loopAnyways = true;
                    break;
                }
            }
        }
        
        Buff b = new Buff(input);
        BuffPanel newBuffPan = new BuffPanel(input,b,null);
        
        cm.registerComponent(newBuffPan);
        jlpEditWindow.add(newBuffPan,JLayeredPane.DEFAULT_LAYER);
        
        buffList.add(b);
        newBuffPan.frontify();
        
    }//GEN-LAST:event_cmdNewBuffActionPerformed

    private void newBuffChainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newBuffChainActionPerformed
        if(!buffChainName.equals("")) {
            // ask to save changes
            int response = JOptionPane.showConfirmDialog(this, "You are already working on a project.  Are you sure you want to do this?", "Save before loading?", JOptionPane.YES_NO_OPTION);
            if(response == JOptionPane.YES_OPTION) {
                response = JOptionPane.showConfirmDialog(this, "Would you like to save now?", "Save before loading?", JOptionPane.YES_NO_OPTION);
                if(response == JOptionPane.YES_OPTION) {
                    // save changes
                    saveBuffChainActionPerformed(null);
                }
                wipeSlate();
            }
            else {
                return;
            }
        }
        String input = "";
        while(input.equals("")) {
            input = JOptionPane.showInputDialog(jlpEditWindow,"Select new Buff Chain Prefix");
            if(input == null) {
                buffChainName = "";
                setTitle("Buff Builder");
                return;
            }
            buffChainName = input;
        }
        setTitle("Buff Builder - " + buffChainName);
        
    }//GEN-LAST:event_newBuffChainActionPerformed

    private void cmdNewAbilityActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmdNewAbilityActionPerformed
        String input = "";
        boolean loopAnyways = false;
        while(input.equals("") || loopAnyways)
        {
            loopAnyways = false;
            input = JOptionPane.showInputDialog(jlpEditWindow,"Select New Ability Name");
            if(input == null)
                return;

            for(int i = 0; i < abilityList.size(); i++) {
                if(abilityList.get(i).name.equals(input))
                {
                    JOptionPane.showMessageDialog(jlpEditWindow, "An ability already exists by that name");
                    loopAnyways = true;
                    break;
                }
            }
        }
        
        Ability b = new Ability(input);
        AbilityPanel newAbilityPan = new AbilityPanel(input,b,null);
        
        cm.registerComponent(newAbilityPan);
        jlpEditWindow.add(newAbilityPan,JLayeredPane.DEFAULT_LAYER);
        
        abilityList.add(b);
        newAbilityPan.frontify();
    }//GEN-LAST:event_cmdNewAbilityActionPerformed

    void wipeSlate() {
        for(int i = abilityList.size()-1; i > -1; i--) {
            abilityList.get(i).ownerPanel.kill(abilityList.get(i).ownerPanel.cmdClose,true);
        }
        for(int i = buffList.size()-1; i > -1 ; i--) {
            buffList.get(i).ownerPanel.kill(buffList.get(i).ownerPanel.cmdClose,true);
        }
    }

    private void loadBuffChainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadBuffChainActionPerformed
                
        // replace existing buff chain
        if(!buffChainName.equals("")) {
            // ask to save changes
            int response = JOptionPane.showConfirmDialog(this, "You are already working on a project.  Are you sure you want to do this?", "Save before loading?", JOptionPane.YES_NO_OPTION);
            if(response == JOptionPane.YES_OPTION) {
                response = JOptionPane.showConfirmDialog(this, "Would you like to save now?", "Save before loading?", JOptionPane.YES_NO_OPTION);
                if(response == JOptionPane.YES_OPTION) {
                    // save changes
                    saveBuffChainActionPerformed(null);
                }
                wipeSlate();
            }
            else {
                return;
            }
        }
        
        
        JFileChooser jfc = new JFileChooser(System.getProperty("user.dir") + "/Projects");
        int ret = jfc.showOpenDialog(null);
        File f = jfc.getSelectedFile();
        if(f == null)
            return;
        loadBCP(f);
    }//GEN-LAST:event_loadBuffChainActionPerformed

    void loadBCP(File f) {        
        String input = "";
        try {
            Scanner s = new Scanner(f);
            String bcn = s.nextLine();
            
            setTitle("Buff Builder - " + bcn);
            buffChainName = bcn;
            
            input = s.nextLine();
            int aCount = Integer.parseInt(input);
            input = s.nextLine();
            int bCount = Integer.parseInt(input);
            
            for(int i = 0; i < aCount; i++) {
                int xPos = Integer.parseInt(s.nextLine());
                int yPos = Integer.parseInt(s.nextLine());     
                String name = s.nextLine();     
                s.nextLine();
                s.nextLine();
                readSavedAbility(s,f,name,xPos,yPos);
            }
            
            for(int i = 0; i < bCount; i++) {
                int xPos = Integer.parseInt(s.nextLine());
                int yPos = Integer.parseInt(s.nextLine());        
                String name = s.nextLine();
                s.nextLine();
                s.nextLine();
                readSavedBuff(s,f,name,xPos,yPos);
            }
            
            for(int i = 0; i < abilityList.size(); i++) {
                abilityList.get(i).ownerPanel.attachLineage();
            }
        }
        catch(Exception e){
            JOptionPane.showMessageDialog(this, "Failed to load the buff chain project.  It may be corrupted.\n" + e.toString() + '\n' + e.getStackTrace());
        }
        
    }
    
    void readSavedBuff(Scanner s, File f, String name, int x, int y) {
        Entity e;
        EntityPanel ep;
        
        
        e = new Buff(name);
        ep = new BuffPanel(name,(Buff)e,null);
        buffList.add((Buff)e);
        
        cm.registerComponent(ep);
        jlpEditWindow.add(ep,JLayeredPane.DEFAULT_LAYER);
        ep.frontify();
        
        
        String input = "";
        int i = 0;
        while(s.hasNext()){
            int virtLeng = ep.virtualList.size();
            if(i >= virtLeng)
                break;
            input = s.nextLine();
            Property cur = ep.virtualList.get(i);
            String propName = cur.getName();
            int spaceIndex = input.indexOf(" ");
            String newVal = input.substring(spaceIndex+1);
            if(cur.getType() == Property.VOID)
            {
                i++;
                continue;
            }else if(cur.getType() == Property.COUNT) {
                int count = Integer.parseInt(newVal);
                for(int m = 0; m < count; m++)
                {
                    Entity inst=null;
                    EntityPanel instPanel=null;
                    input = s.nextLine();//ignore declaration line
                    if(propName.indexOf("numInstantAction") != -1) {
                        inst = new InstantAction();
                        instPanel = new InstantActionPanel("InstantAction",inst,ep);
                        e.instant++;
                    }
                    else if(propName.indexOf("numPeriodicAction") != -1) {
                        inst = new PeriodicAction();
                        instPanel = new PeriodicActionPanel("PeriodicAction",inst,ep);
                        e.periodic++;
                    }
                    else if(propName.indexOf("numOverTimeAction") != -1) {
                        inst = new OverTimeAction();
                        instPanel = new OverTimeActionPanel("OverTimeAction",inst,ep);
                        e.over++;
                    }
                    else if(propName.indexOf("numEntityModifier") != -1) {
                        inst = new EntityModifier();
                        instPanel = new EntityModifierPanel("EntityModifier",inst,ep);
                        e.modifiers++;
                    }
                    else if(propName.indexOf("numEntityBoolModifier") != -1) {
                        inst = new EntityBoolModifier();
                        instPanel = new EntityBoolModifierPanel("EntityBoolModifer",inst,ep);
                        e.bools++;
                    }
                    else if(propName.indexOf("numFinishCondition") != -1) {
                        inst = new FinishCondition();
                        instPanel = new FinishConditionPanel("FinishCondition",inst,ep);
                        e.finishers++;
                    }
                    cm.registerComponent(instPanel);
                    jlpEditWindow.add(instPanel,JLayeredPane.DEFAULT_LAYER);
                    instPanel.frontify();
                    ep.children.add(instPanel);
                    
                    instPanel.setLocation(x,y+50);
                    
                    int holder = i;
                    i=0;
                    try{
                        while(s.hasNext()){
                            int virtLeng0 = instPanel.virtualList.size();
                            if(i >= virtLeng0)
                                break;
                            input = s.nextLine();
                            Property cur0 = instPanel.virtualList.get(i);
                            String propName0 = cur0.getName();
                            int spaceIndex0 = input.indexOf(" ");
                            if(cur0.getType() == Property.VOID || cur0.getType() == Property.COUNT)
                            {
                                i++;
                                continue;
                            }
                            String newVal0 = input.substring(spaceIndex0+1);
                            cur0.overwrite(newVal0);
                            instPanel.populate(instPanel.propertyData);
                            
                            i++;
                        }
                        if(instPanel instanceof PeriodicActionPanel) {
                            InstantActionPanel terminus = readIA(s,f,instPanel,inst);
                            terminus.setLocation(x,y+100);
                        }
                    }
                    catch(Exception e1) {
                        JOptionPane.showMessageDialog(this,"please hold :(");
                    }
                    i=holder;
                }
            }
            
            cur.overwrite(newVal);
            ep.populate(ep.propertyData);
            
            ep.setLocation(x,y);
            
            i++;
        }
        
    }

    InstantActionPanel readIA(Scanner s, File f, EntityPanel ep, Entity e) {
        InstantAction ia = new InstantAction();
        InstantActionPanel iap = new InstantActionPanel("InstantAction",ia,ep);
        ep.children.add(iap);
        cm.registerComponent(iap);
        jlpEditWindow.add(iap,JLayeredPane.DEFAULT_LAYER);
        iap.frontify();        
        
        String input = "";
        
        // load instantAction
        int i = 0;
        while(s.hasNext()){
            int virtLeng = iap.virtualList.size();
            if(i >= virtLeng)
                break;
            input = s.nextLine();
            Property cur = iap.virtualList.get(i);
            String propName = cur.getName();
            int spaceIndex = input.indexOf(" ");
            if(cur.getType() == Property.VOID || cur.getType() == Property.COUNT)
            {
                i++;
                continue;
            }
            String newVal = input.substring(spaceIndex+1);
            cur.overwrite(newVal);
            iap.populate(iap.propertyData);
            
            i++;
        }
        return iap;
    }

    void readSavedAbility(Scanner s, File f, String name, int x, int y) {
        Entity e;
        EntityPanel ep;      
        
        e = new Ability(name);
        ep = new AbilityPanel(name,(Ability)e,null);
        abilityList.add((Ability)e);
        
        cm.registerComponent(ep);
        jlpEditWindow.add(ep,JLayeredPane.DEFAULT_LAYER);
        ep.frontify();
        
        
        // load IA
        InstantActionPanel iap = readIA(s,f,ep,e);
        
        // load body
        int i = 0;
        String input = "";
        while(s.hasNext()){
            int virtLeng = ep.virtualList.size();
            if(i >= virtLeng)
                break;
            input = s.nextLine();
            Property cur = ep.virtualList.get(i);
            String propName = cur.getName();
            int spaceIndex = input.indexOf(" ");
            String newVal = input.substring(spaceIndex+1);
            if(cur.getType() == Property.VOID)
            {
                i++;
                continue;
            }
            cur.overwrite(newVal);
            ep.populate(ep.propertyData);
            
            i++;
        }
        
        ep.setLocation(new Point(x,y));
        iap.setLocation(new Point(x,y+50));
    }


    private void jmiReadmeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jmiReadmeActionPerformed
        try {
            URI uri = new URI("https://docs.google.com/document/d/1SAOUPim5W4lq3qbhObIXBnK2YYmIE2HW2FWUCM57bqU");
            Desktop.getDesktop().browse(uri);
        } catch (URISyntaxException e) {
        } catch (IOException e) {
        }
        
    }//GEN-LAST:event_jmiReadmeActionPerformed

    void exportBuff(PrintWriter pw, Entity e, EntityPanel ep) {
        pw.println("TXT");
        pw.println("entityType \"Buff\"");
        
        ArrayList<InstantAction> ia = new ArrayList<InstantAction>();                    
        ArrayList<PeriodicAction> pa = new ArrayList<PeriodicAction>();                    
        ArrayList<OverTimeAction> ot = new ArrayList<OverTimeAction>();                    
        ArrayList<EntityModifier> em = new ArrayList<EntityModifier>();                    
        ArrayList<EntityBoolModifier> bm = new ArrayList<EntityBoolModifier>();                    
        ArrayList<FinishCondition> fc = new ArrayList<FinishCondition>();
        
        for(int j = 0; j < ep.children.size(); j++) {
            EntityPanel childPanel = ep.children.get(j);
            Entity child = childPanel.attachedEntity;
            if(child instanceof InstantAction)
                ia.add((InstantAction)child);
            else if(child instanceof PeriodicAction)
                pa.add((PeriodicAction)child);
            else if(child instanceof OverTimeAction)
                ot.add((OverTimeAction)child);
            else if(child instanceof EntityModifier)
                em.add((EntityModifier)child);
            else if(child instanceof EntityBoolModifier)
                bm.add((EntityBoolModifier)child);
            else if(child instanceof FinishCondition)
                fc.add((FinishCondition)child);
        }
        
        
        for(int j = 0; j < e.props.size(); j++) {
            Property cur = e.props.get(j);
            cur.populate(pw);
            if(cur.getType() == Property.COUNT) {
                if(cur.getName().equals("numInstantActions")) {
                    for(int k = 0; k < ia.size(); k++) {
                        pw.println("instantAction");
                        InstantAction a = ia.get(k);
                        for(int m = 0; m < a.props.size(); m++)
                            a.props.get(m).populate(pw);
                    }
                }
                else if(cur.getName().equals("numPeriodicActions")) {
                    for(int k = 0; k < pa.size(); k++) {
                        pw.println("periodicAction");
                        PeriodicAction a = pa.get(k);
                        for(int m = 0; m < a.props.size(); m++)
                            a.props.get(m).populate(pw);
                        PeriodicActionPanel pap = (PeriodicActionPanel)a.ownerPanel;
                        EntityPanel childEP = pap.children.get(0);
                        for(int m = 0; m < childEP.attachedEntity.props.size(); m++)
                            childEP.attachedEntity.props.get(m).populate(pw);
                    }
                }
                else if(cur.getName().equals("numOverTimeActions")) {
                    for(int k = 0; k < ot.size(); k++) {
                        pw.println("overTimeAction");
                        OverTimeAction a = ot.get(k);
                        for(int m = 0; m < a.props.size(); m++)
                            a.props.get(m).populate(pw);
                    }
                    
                }
                else if(cur.getName().equals("numEntityModifiers")) {
                    for(int k = 0; k < em.size(); k++) {
                        pw.println("entityModifier");
                        EntityModifier a = em.get(k);
                        for(int m = 0; m < a.props.size(); m++)
                            a.props.get(m).populate(pw);
                    }
                    
                }
                else if(cur.getName().equals("numEntityBoolModifiers")) {
                    for(int k = 0; k < bm.size(); k++) {
                        pw.println("entityBoolModifier");
                        EntityBoolModifier a = bm.get(k);
                        for(int m = 0; m < a.props.size(); m++)
                            a.props.get(m).populate(pw);
                    }
                    
                }
                else if(cur.getName().equals("numFinishConditions")) {
                    for(int k = 0; k < fc.size(); k++) {
                        pw.println("finishCondition");
                        FinishCondition a = fc.get(k);
                        for(int m = 0; m < a.props.size(); m++)
                            a.props.get(m).populate(pw);
                    }
                    
                }
            }
        }
    }

    void exportAbility(PrintWriter pw, Entity e, EntityPanel ep) {
        pw.println("TXT");
        pw.println("entityType \"Ability\"");

        if(ep.children.size() != 0)
        {
            EntityPanel childPanel = ep.children.get(0);
            Entity child = childPanel.attachedEntity;
            for(int j = 0; j < child.props.size(); j++) {
                Property cur = child.props.get(j);
                cur.populate(pw);
            }
        }
        
        for(int j = 0; j < e.props.size(); j++) {
            Property cur = e.props.get(j);
            cur.populate(pw);
        }
    }

    private void saveBuffChainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveBuffChainActionPerformed
        String input = buffChainName;
        while(input.equals("")) {
            input = JOptionPane.showInputDialog(jlpEditWindow,"Please type in the Buff Chain Prefix of the desired buff chain");
            if(input == null)
                return;
            buffChainName = input;
            this.setTitle("Buff Buillder - " + buffChainName);
        }
        int aNum = abilityList.size();
        int bNum = buffList.size();
        File f = new File("Projects/" + buffChainName + ".bcp");
        try {
            PrintWriter pw = new PrintWriter(f);
            pw.println(buffChainName);
            pw.println(aNum);
            pw.println(bNum);
            
            // save abilities
            for(int i = 0; i < aNum; i++) {
                Entity e = abilityList.get(i);
                EntityPanel ep = e.ownerPanel;
                pw.println((int)ep.getLocation().getX());
                pw.println((int)ep.getLocation().getY());
                pw.println(e.name);
                exportAbility(pw,e,ep);
            }
            
            // save buffs
            for(int i = 0; i < bNum; i++) {
                Entity e = buffList.get(i);
                EntityPanel ep = e.ownerPanel;
                pw.println((int)ep.getLocation().getX());
                pw.println((int)ep.getLocation().getY());
                pw.println(e.name);
                exportBuff(pw,e,ep);
            }
            pw.flush();
            pw.close();
            
            // establish parents
            
            
            JOptionPane.showMessageDialog(this,"Project " + buffChainName + " saved successfully.");
        } catch (FileNotFoundException e) {
        }
    }//GEN-LAST:event_saveBuffChainActionPerformed

    private void importFromEntityActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importFromEntityActionPerformed
        String input = "";        
        JFileChooser jfc = new JFileChooser(System.getProperty("user.dir") + "/GameInfo");
        int ret = jfc.showOpenDialog(null);
        File f = jfc.getSelectedFile();
        if(f == null)
            return;
        try {
            Scanner s = new Scanner(f);
            String encoding = s.nextLine();
            if(encoding.indexOf("TXT") != -1) {
                // ready to go :D
            }
            else if(encoding.indexOf("BIN") != -1) {
                // TODO: run ConvertData.exe
                String path = f.getAbsolutePath();
                path = path.substring(0,path.lastIndexOf("\\")+1);
                path = path + "ConvertData_Rebellion.exe";
                s.close();
                String fName = f.getName();
                String execString =  path + " entity " + fName + ' ' + fName + " txt";
                JOptionPane.showMessageDialog(this,execString);
                System.err.println(execString);
                PrintWriter pw = new PrintWriter(path);
                Process process = new ProcessBuilder(path,"entity", fName,fName,"txt").start();
                JOptionPane.showMessageDialog(this,"process created");
                process.waitFor();
                JOptionPane.showMessageDialog(this,"process waited");
                process.destroy();
                JOptionPane.showMessageDialog(this,"process destroyed");
                //Process p1 = Runtime.getRuntime().exec(execString);
                //p1.waitFor();
                s=new Scanner(f);
                s.nextLine();
            }
            else {
                JOptionPane.showMessageDialog(this, "Desired file is corrupted.  Code 0");
                throw new Exception();
            }
            String entityType = s.nextLine();
            boolean type = false;// F=Buff, T=Ability
            Entity e;
            EntityPanel ep;
            if(entityType.equals("entityType \"Buff\"")) {
                type = false;
                e = new Buff(f.getName().substring(4));
                ep = new BuffPanel(f.getName().substring(4),(Buff)e,null);
                buffList.add((Buff)e);
            }
            else if(entityType.equals("entityType \"Ability\"")) {
                type = true;
                e = new Ability(f.getName().substring(7));
                ep = new AbilityPanel(f.getName().substring(7),(Ability)e,null);
                abilityList.add((Ability)e);
            }
            else {
                JOptionPane.showMessageDialog(this, "Desired file is corrupted.  Code 1");
                throw new Exception();
            }
            cm.registerComponent(ep);
            jlpEditWindow.add(ep,JLayeredPane.DEFAULT_LAYER);
            ep.frontify();
            String fullFile = "";
            int i = 0;
            if(ep instanceof AbilityPanel) {
                InstantAction ia = new InstantAction();
                InstantActionPanel iap = new InstantActionPanel("InstantAction",ia,ep);
                ep.children.add(iap);
                cm.registerComponent(iap);
                jlpEditWindow.add(iap,JLayeredPane.DEFAULT_LAYER);
                iap.frontify();
                while(s.hasNext()){
                    int virtLeng = iap.virtualList.size();
                    if(i >= virtLeng)
                        break;
                    input = s.nextLine();
                    fullFile = fullFile + input + '\n';
                    Property cur = iap.virtualList.get(i);
                    String propName = cur.getName();
                    int spaceIndex = input.indexOf(" ");
                    if(cur.getType() == Property.VOID || cur.getType() == Property.COUNT)
                    {
                        i++;
                        continue;
                    }
                    String newVal = input.substring(spaceIndex+1);
                    cur.overwrite(newVal);
                    iap.populate(iap.propertyData);
                    
                    i++;
                }
                i = 0;
            }
            while(s.hasNext()){
                int virtLeng = ep.virtualList.size();
                if(i >= virtLeng)
                    break;
                input = s.nextLine();
                fullFile = fullFile + input + '\n';
                Property cur = ep.virtualList.get(i);
                String propName = cur.getName();
                int spaceIndex = input.indexOf(" ");
                String newVal = input.substring(spaceIndex+1);
                if(cur.getType() == Property.VOID)
                {
                    i++;
                    continue;
                }else if(cur.getType() == Property.COUNT && ep instanceof BuffPanel) {
                    int count = Integer.parseInt(newVal);
                    for(int m = 0; m < count; m++)
                    {
                        Entity inst=null;
                        EntityPanel instPanel=null;
                        input = s.nextLine();//ignore declaration line
                        if(propName.indexOf("numInstantAction") != -1) {
                            inst = new InstantAction();
                            instPanel = new InstantActionPanel("InstantAction",inst,ep);
                            e.instant++;
                        }
                        else if(propName.indexOf("numPeriodicAction") != -1) {
                            inst = new PeriodicAction();
                            instPanel = new PeriodicActionPanel("PeriodicAction",inst,ep);
                            e.periodic++;
                        }
                        else if(propName.indexOf("numOverTimeAction") != -1) {
                            inst = new OverTimeAction();
                            instPanel = new OverTimeActionPanel("OverTimeAction",inst,ep);
                            e.over++;
                        }
                        else if(propName.indexOf("numEntityModifier") != -1) {
                            inst = new EntityModifier();
                            instPanel = new EntityModifierPanel("EntityModifier",inst,ep);
                            e.modifiers++;
                        }
                        else if(propName.indexOf("numEntityBoolModifier") != -1) {
                            inst = new EntityBoolModifier();
                            instPanel = new EntityBoolModifierPanel("EntityBoolModifer",inst,ep);
                            e.bools++;
                        }
                        else if(propName.indexOf("numFinishCondition") != -1) {
                            inst = new FinishCondition();
                            instPanel = new FinishConditionPanel("FinishCondition",inst,ep);
                            e.finishers++;
                        }
                        cm.registerComponent(instPanel);
                        jlpEditWindow.add(instPanel,JLayeredPane.DEFAULT_LAYER);
                        instPanel.frontify();
                        ep.children.add(instPanel);
                        int holder = i;
                        i=0;
                        try{
                            while(s.hasNext()){
                                int virtLeng0 = instPanel.virtualList.size();
                                if(i >= virtLeng0)
                                    break;
                                input = s.nextLine();
                                Property cur0 = instPanel.virtualList.get(i);
                                String propName0 = cur0.getName();
                                int spaceIndex0 = input.indexOf(" ");
                                if(cur0.getType() == Property.VOID || cur0.getType() == Property.COUNT)
                                {
                                    i++;
                                    continue;
                                }
                                String newVal0 = input.substring(spaceIndex0+1);
                                cur0.overwrite(newVal0);
                                instPanel.populate(instPanel.propertyData);
                                
                                i++;
                            }
                            if(instPanel instanceof PeriodicActionPanel) {
                                InstantActionPanel terminus = readIA(s,f,instPanel,inst);
                                terminus.setLocation(40,40);
                            }
                        }
                        catch(Exception e1) {
                            JOptionPane.showMessageDialog(this,"please hold :(");
                        }
                        i=holder;
                    }
                }
                
                cur.overwrite(newVal);
                ep.populate(ep.propertyData);
                
                i++;
            }
            //JOptionPane.showMessageDialog(this,fullFile);
        } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(this, "Failed to open file\n" + e.toString());
            
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "Failed to open file.  The entity file may be corrupted.\n" + e.toString());
            
        }
    }//GEN-LAST:event_importFromEntityActionPerformed

    private void jmiHelpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jmiHelpActionPerformed
        try {
            URI uri = new URI("http://forums.sinsofasolarempire.com/455984");
            Desktop.getDesktop().browse(uri);
        } catch (URISyntaxException e) {
        } catch (IOException e) {
        }
    }//GEN-LAST:event_jmiHelpActionPerformed

    private void jmiSourceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jmiSourceActionPerformed
        try {
            URI uri = new URI("https://code.google.com/p/buff-builder/");
            Desktop.getDesktop().browse(uri);
        } catch (URISyntaxException e) {
        } catch (IOException e) {
        }
    }//GEN-LAST:event_jmiSourceActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(jfMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null,
                                                                                ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(jfMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null,
                                                                                ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(jfMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null,
                                                                                ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(jfMainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null,
                                                                                ex);
        }
        //</editor-fold>

        /* Create and display the form */
        //java.awt.EventQueue.invokeLater(new Runnable() {
            //public void run() {
                jfMainFrame mf = new jfMainFrame();
                mf.setVisible(true);
                mf.setTitle("Buff Builder");
                if(args.length == 2) {
                    File f = new File(args[1]);
                    mf.loadBCP(f);
                }
            //}
        //});
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cmdNewAbility;
    private javax.swing.JButton cmdNewBuff;
    private javax.swing.JMenuItem exportToBuffChain;
    private javax.swing.JMenuItem importFromEntity;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JLayeredPane jlpEditWindow;
    private javax.swing.JMenuItem jmiHelp;
    private javax.swing.JMenuItem jmiReadme;
    private javax.swing.JMenuItem jmiSource;
    private javax.swing.JPanel jpToolbox;
    private javax.swing.JMenuItem loadBuffChain;
    private javax.swing.JMenuItem newBuffChain;
    private javax.swing.JMenuItem saveBuffChain;
    // End of variables declaration//GEN-END:variables

}
